home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / lib / cryptsetup / cryptdisks.functions < prev   
Text File  |  2009-10-14  |  14KB  |  635 lines

  1. #
  2. # This file is for inclusion with
  3. #    . /lib/cryptsetup/cryptdisks.functions
  4. # and should not be executed directly.
  5.  
  6. PATH="/sbin:/bin"
  7. TABFILE="/etc/crypttab"
  8. CRYPTDISKS_ENABLE="Yes"
  9.  
  10. #set -x
  11.  
  12. # Sanity checks
  13. [ -x /sbin/cryptsetup ] || exit 0
  14. [ -f "$TABFILE"       ] || exit 0
  15.  
  16. . /lib/lsb/init-functions
  17.  
  18. if [ -r /etc/default/cryptdisks ]; then
  19.     . /etc/default/cryptdisks
  20. fi
  21.  
  22. MOUNT="$CRYPTDISKS_MOUNT"
  23.  
  24. LOUD=""
  25.  
  26. # Parses the option field from the crypttab file
  27. parse_opts () {
  28.     local opts opt IFS PARAM VALUE
  29.  
  30.     # Strip comments - https://bugs.launchpad.net/bugs/185380
  31.     opts=$(echo -n $1 | sed 's/ *#.*//')
  32.     PARAMS=""
  33.     CHECK=""
  34.     CHECKARGS=""
  35.     PRECHECK=""
  36.     TRIES="3"
  37.     TMPFS=""
  38.     MAKESWAP=""
  39.     USELUKS=""
  40.     KEYSCRIPT=""
  41.     IGNORE=""
  42.  
  43.     # Parse the options field, convert to cryptsetup parameters
  44.     # and construct the command line
  45.     IFS=','
  46.     for opt in $opts; do
  47.         PARAM=$(echo "$opt" | sed 's/=.*//')
  48.         VALUE=$(echo "$opt" | sed '/=/!d;s/^.*=//')
  49.         
  50.         case "$PARAM" in 
  51.         readonly)
  52.             PARAMS="$PARAMS -r"
  53.             ;;
  54.         cipher)
  55.             if [ -z "$VALUE" ]; then
  56.                 log_warning_msg "$dst: no value for cipher option, skipping"
  57.                 return 1
  58.             fi
  59.             PARAMS="$PARAMS -c $VALUE"
  60.             ;;
  61.         size)
  62.             if [ -z "$VALUE" ] || echo "$VALUE" | grep -q "^[[:digit:]]\+$" && [ "$VALUE" -gt 0 ]; then
  63.                 PARAMS="$PARAMS -s $VALUE"
  64.             else
  65.                 log_warning_msg "$dst: option size used with an incorrect argument, skipping"
  66.                 return 1
  67.             fi
  68.             ;;
  69.         hash)
  70.             if [ -z "$VALUE" ]; then
  71.                 log_warning_msg "$dst: no value for hash option, skipping"
  72.                 return 1
  73.             fi
  74.             PARAMS="$PARAMS -h $VALUE"
  75.             ;;
  76.         offset)
  77.             if [ -z "$VALUE" ]; then
  78.                 log_warning_msg "$dst: no value for offset option, skipping"
  79.                 return 1
  80.             fi
  81.             PARAMS="$PARAMS -o $VALUE"
  82.             ;;
  83.         skip)
  84.             if [ -z "$VALUE" ]; then
  85.                 log_warning_msg "$dst: no value for skip option, skipping"
  86.                 return 1
  87.             fi
  88.             PARAMS="$PARAMS -p $VALUE"
  89.             ;;
  90.         verify)
  91.             PARAMS="$PARAMS -y"
  92.             ;;
  93.         check)
  94.             if [ -z "$VALUE" ]; then
  95.                 VALUE="$CRYPTDISKS_CHECK"
  96.             fi
  97.             if [ -x "$VALUE" ]; then
  98.                 CHECK="$VALUE"
  99.             elif [ -x "/lib/cryptsetup/checks/$VALUE" ]; then
  100.                 CHECK="/lib/cryptsetup/checks/$VALUE"
  101.             else
  102.                 log_warning_msg "check $VALUE is not an executable script, skipping"
  103.                 return 1
  104.             fi
  105.             ;;
  106.         checkargs)
  107.             if [ -n "$VALUE" ]; then
  108.                 CHECKARGS="$VALUE"
  109.             fi
  110.             ;;
  111.         precheck)
  112.             if [ -z "$VALUE" ]; then
  113.                 VALUE="$CRYPTDISKS_PRECHECK"
  114.             fi
  115.             if [ -x "$VALUE" ]; then
  116.                 PRECHECK="$VALUE"
  117.             elif [ -x "/lib/cryptsetup/checks/$VALUE" ]; then
  118.                 PRECHECK="/lib/cryptsetup/checks/$VALUE"
  119.             else
  120.                 log_warning_msg "precheck $VALUE is not an executable script, skipping"
  121.                 return 1
  122.             fi
  123.             ;;
  124.         tries)
  125.             if echo "$VALUE" | grep -q "^[[:digit:]]\+$" && [ "$VALUE" -gt 0 ]; then
  126.                 TRIES="$VALUE"
  127.             else
  128.                 log_warning_msg "$dst: option tries used with an incorrect argument - forced to $TRIES"
  129.             fi
  130.             ;;
  131.         swap)
  132.             MAKESWAP="yes"
  133.             SWCHECK="/lib/cryptsetup/checks/un_vol_id"
  134.             SWCHECKARGS="swap"
  135.             ;;
  136.         tmp)
  137.             if [ -z "$VALUE" ]; then
  138.                 TMPFS="ext2"
  139.             else
  140.                 TMPFS="$VALUE"
  141.             fi
  142.             ;;
  143.         luks)
  144.             USELUKS="yes"
  145.             ;;
  146.         noearly)
  147.             if [ "$INITSTATE" = "early" ]; then
  148.                 IGNORE="yes"
  149.             fi
  150.             ;;
  151.         noauto)
  152.             if [ -n "$INITSTATE" ]; then
  153.                 IGNORE="yes"
  154.             fi
  155.             ;;
  156.         loud)
  157.             LOUD="yes"
  158.             ;;
  159.         keyscript)
  160.             if [ -n "$KEYSCRIPT" ]; then
  161.                 log_warning_msg "$dst: multiple key decryption options are not allowed together, skipping"
  162.                 return 1
  163.             elif [ -x "$VALUE" ]; then
  164.                 KEYSCRIPT="$VALUE"
  165.             elif [ -x "/lib/cryptsetup/scripts/$VALUE" ]; then
  166.                 KEYSCRIPT="/lib/cryptsetup/scripts/$VALUE"
  167.             elif [ -z "$VALUE" ]; then
  168.                 log_warning_msg "$dst: no value for keyscript option, skipping"
  169.                 return 1
  170.             else
  171.                 log_warning_msg "script $VALUE is not an executable script, skipping"
  172.                 return 1
  173.             fi
  174.             ;;
  175.         esac
  176.     done
  177.  
  178.     return 0
  179. }
  180.  
  181. # Set up loopback devices
  182. lo_setup () {
  183.     #local loopdev
  184.  
  185.     if [ ! -f "$src" ]; then
  186.         return 0
  187.     fi
  188.  
  189.     if [ ! -x /sbin/losetup ]; then
  190.         return 1
  191.     fi
  192.  
  193.     if ! grep -q "[[:space:]]loop$" /proc/devices; then
  194.         modprobe -qb loop > /dev/null 2>&1 || return 1
  195.     fi
  196.  
  197.     loopdev=$(losetup -f 2> /dev/null) || return 1
  198.  
  199.     losetup "$loopdev" "$src" || return 1
  200.     src="$loopdev"
  201.     return 0
  202. }
  203.  
  204. rm_lo_setup () {
  205.     if [ ! -f "$src" ]; then
  206.         return 0
  207.     fi
  208.  
  209.     if [ -n "$loopdev" ]; then
  210.         losetup -d "$loopdev" || return 1
  211.     fi
  212.     return 0
  213. }
  214.  
  215. # Sanity check for keys
  216. check_key () {
  217.     local GMODE OMODE OWNER GROUP
  218.  
  219.     # If the keyscript option is set, the "key" is just an argument to
  220.     # the keyscript and not necessarily a file
  221.     if [ -n "$KEYSCRIPT" ]; then
  222.         return 0
  223.     fi
  224.  
  225.     if [ -z "$key" ] || [ "$key" = "none" ]; then
  226.         key=""
  227.         return 0
  228.     fi
  229.  
  230.     if [ ! -e "$key" ]; then
  231.         log_warning_msg "$dst: keyfile not found"
  232.         return 1
  233.     fi
  234.  
  235.     # stat is unfortunately in /usr/bin...
  236.     OMODE=$(ls -l "$key" | sed 's/[[:space:]].*//;s/^.\{7\}//')
  237.     GMODE=$(ls -l "$key" | sed 's/[[:space:]].*//;s/^.\{4\}\(.\{3\}\).*/\1/')
  238.     GROUP=$(ls -l "$key" | sed 's/^.\{11\}[^[:space:]]* [^[:space:]]* \([^[:space:]]*\).*/\1/')
  239.     # regex needs to work if keyfile has xattrs - https://launchpad.net/bugs/231339
  240.     OWNER=$(ls -l "$key" | sed 's/^.\{10\}[+]\?.[^[:space:]]* \([^[:space:]]*\).*/\1/')
  241.  
  242.     # LUKS requires a persistent key, /dev/*random is not supported
  243.     if [ "$USELUKS" = "yes" ] && [ "$key" != "${key%random}" ]; then
  244.         log_warning_msg "$dst: LUKS does not work with random data as key"
  245.         return 1
  246.     fi
  247.  
  248.     # Check owner
  249.     if [ "$OWNER" != "root" ]; then
  250.         log_warning_msg "$dst: INSECURE OWNER FOR $key, see /usr/share/doc/cryptsetup/README.Debian."
  251.     fi
  252.  
  253.     # If key is random, we're done
  254.     if [ "$key" != "${key%random}" ]; then
  255.         return 0
  256.     fi
  257.  
  258.     # Check group and other permissions
  259.     if [ "$OMODE" != "---" ] || [ "$GROUP" != "root" ] && [ "$GMODE" != "---" ]; then
  260.         log_warning_msg "$dst: INSECURE MODE FOR $key, see /usr/share/doc/cryptsetup/README.Debian."
  261.     fi
  262.  
  263.     return 0
  264. }
  265.  
  266. # Setup a luks mapping
  267. do_luks () {
  268.     local tried keyscriptarg
  269.     tried=0
  270.     keyscriptarg=""
  271.  
  272.     if ! cryptsetup isLuks "$src" >/dev/null 2>&1; then
  273.         log_warning_msg "$dst: device '$src' is not a LUKS partition, skipping"
  274.         return 1
  275.     fi
  276.  
  277.     if [ -n "$KEYSCRIPT" ]; then
  278.         # keyscript => "key" is just an argument to the keyscript
  279.         keyscriptarg="$key"
  280.         key="-"
  281.     elif [ -z "$key" ]; then
  282.         # no keyscript, no key => password
  283.         keyscriptarg="Enter passphrase to unlock the disk $src ($dst): "
  284.         key="-"
  285.         KEYSCRIPT="/lib/cryptsetup/askpass"
  286.     elif [ "$key" != "${key%/dev/*}" ]; then
  287.         # no keyscript, device key => special treatment
  288.         keyscriptarg=""
  289.         key="$key"
  290.         KEYSCRIPT=""
  291.     else
  292.         # no keyscript, key => file input
  293.         keyscriptarg="$key"
  294.         key="-"
  295.         KEYSCRIPT="cat"
  296.     fi
  297.  
  298.     PARAMS="$PARAMS --key-file=$key"
  299.  
  300.     while [ "$tried" -lt "$TRIES" ]; do
  301.         if [ -n "$KEYSCRIPT" ]; then
  302.             if "$KEYSCRIPT" "$keyscriptarg" | cryptsetup $PARAMS luksOpen "$src" "$dst"; then
  303.                 break
  304.             fi
  305.         else
  306.             if cryptsetup $PARAMS luksOpen "$src" "$dst"; then
  307.                 break
  308.             fi
  309.         fi
  310.  
  311.         tried=$(( $tried + 1 ))
  312.         if [ "$tried" -ge "$TRIES" ]; then
  313.             return 1
  314.         fi
  315.     done
  316.  
  317.     if [ -n "$CHECK" ] && ! "$CHECK" "/dev/mapper/$dst" $CHECKARGS; then
  318.         log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed"
  319.         cryptsetup luksClose "$dst"
  320.         return 1
  321.     fi
  322.  
  323.     return 0
  324. }
  325.  
  326. # Setup a regular mapping
  327. do_noluks () {
  328.     local pre_out tried keyscriptarg
  329.     tried=0
  330.     keyscriptarg=""
  331.  
  332.     if [ -z "$PRECHECK" ]; then
  333.         PRECHECK="/lib/cryptsetup/checks/un_vol_id"
  334.     fi
  335.  
  336.     if ! pre_out=$("$PRECHECK" "$src" 2> /dev/null) && \
  337.        [ "$MAKESWAP" != "yes" ] && \
  338.        ! /lib/cryptsetup/checks/vol_id "$src" swap >/dev/null; then
  339.         log_warning_msg "$dst: the precheck for '$src' failed: $pre_out"
  340.         return 1
  341.     fi
  342.  
  343.     if [ -n "$KEYSCRIPT" ]; then
  344.         # keyscript => "key" is just an argument to the keyscript
  345.         keyscriptarg="$key"
  346.         key="-"
  347.     elif [ -z "$key" ]; then
  348.         # no keyscript, no key => password
  349.         keyscriptarg="Enter passphrase to unlock the disk $src ($dst): "
  350.         key="-"
  351.         KEYSCRIPT="/lib/cryptsetup/askpass"
  352.     else
  353.         # no keyscript, key => file input
  354.         keyscriptarg=""
  355.         key="$key"
  356.         KEYSCRIPT=""
  357.     fi
  358.  
  359.     PARAMS="$PARAMS --key-file=$key"
  360.  
  361.     while [ "$tried" -lt "$TRIES" ]; do
  362.         if [ -n "$KEYSCRIPT" ]; then
  363.             "$KEYSCRIPT" "$keyscriptarg" | cryptsetup $PARAMS create "$dst" "$src"
  364.         else
  365.             cryptsetup $PARAMS create "$dst" "$src"
  366.         fi
  367.  
  368.         if [ -z "$CHECK" ] || "$CHECK" "/dev/mapper/$dst" $CHECKARGS; then
  369.             break
  370.         else
  371.             log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed - maybe the password is wrong"
  372.             cryptsetup remove "$dst"
  373.         fi
  374.  
  375.         tried=$(( $tried + 1 ))
  376.         if [ "$tried" -ge "$TRIES" ]; then
  377.             return 1
  378.         fi
  379.     done
  380.  
  381.     return 0
  382. }
  383.  
  384. # Premounts file systems
  385. mount_fs () {
  386.     local point
  387.     MOUNTED=""
  388.  
  389.     for point in $MOUNT; do
  390.         if mount "$point" >/dev/null; then
  391.             MOUNTED="$MOUNTED $point"
  392.         fi
  393.     done
  394. }
  395.  
  396. # Postunmounts file systems
  397. umount_fs () {
  398.     local point
  399.  
  400.     for point in $MOUNTED; do
  401.         umount "$point" >/dev/null
  402.     done
  403. }
  404.  
  405. # Prepares swap partitions using random keys
  406. do_swap () {
  407.     local swap_out
  408.  
  409.     if [ "$MAKESWAP" != "yes" ] || [ ! -b "/dev/mapper/$dst" ]; then
  410.         return 0
  411.     fi
  412.  
  413.     if swap_out=$(/lib/cryptsetup/checks/un_vol_id "/dev/mapper/$dst" 2> /dev/null) || \
  414.        /lib/cryptsetup/checks/vol_id "/dev/mapper/$dst" swap > /dev/null 2>&1; then
  415.         mkswap "/dev/mapper/$dst" > /dev/null 2>&1
  416.     else
  417.         log_warning_msg "$dst: the check for '/dev/mapper/$dst' failed. /dev/mapper/$dst contains data: $swap_out"
  418.         do_close
  419.         return 1
  420.     fi
  421.  
  422.     return 0
  423. }
  424.  
  425. # Prepares tmp partitions using random keys
  426. do_tmp () {
  427.     if [ "x$TMPFS" = "x" ] || [ ! -b "/dev/mapper/$dst" ]; then
  428.         return 0
  429.     fi
  430.  
  431.     mkfs -t $TMPFS -q "/dev/mapper/$dst" > /dev/null 2>&1 || return 1
  432.     mount -t $TMPFS "/dev/mapper/$dst" /tmp || return 1
  433.     chmod 1777 /tmp
  434.     umount /tmp
  435.     return 0
  436. }
  437.  
  438. # Removes a mapping
  439. do_close () {
  440.     local found IFS opt
  441.  
  442.     found="no"
  443.     IFS=','
  444.     for opt in $opts; do
  445.         if [ "$opt" = "luks" ]; then
  446.             found="yes"
  447.             break
  448.         fi
  449.     done
  450.  
  451.     if [ "$found" = "yes" ]; then
  452.         cryptsetup luksClose "$dst"
  453.     else
  454.         cryptsetup remove "$dst"
  455.     fi
  456.     return $?
  457. }
  458.  
  459. load_optimized_module () {
  460.     local module optmodule
  461.     module="$1"
  462.  
  463.     optmodule=$(find "/lib/modules/$(uname -r)/kernel/arch" -name "${module}*.ko" 2> /dev/null)
  464.     if [ -n "$optmodule" ] && [ "$(echo -n "$optmodule" | wc -l)" -eq 1 ]; then
  465.         modprobe "$optmodule" 2>/dev/null && return 0
  466.     fi
  467.  
  468.     modprobe "$module" 2>/dev/null || return 1
  469.     return 0
  470. }
  471.  
  472. # Sets up all entries in crypttab
  473. handle_crypttab_line_start () {
  474.     dst=$1
  475.     src=$2
  476.     key=$3
  477.     opts=$4
  478.  
  479.     # Make sure that all fields are present
  480.     if [ -z "$dst" ]; then
  481.         continue
  482.     elif [ -z "$src" ] || [ -z "$key" ] || [ -z "$opts" ]; then
  483.         device_msg "$dst" "skipped, missing parameters"
  484.         continue
  485.     fi
  486.  
  487.     # parse UUID= symlinks
  488.     if [ "${src#UUID=}" != "$src" ]; then
  489.         src="/dev/disk/by-uuid/${src#UUID=}"
  490.     elif [ "${src#LABEL=}" != "$src" ]; then
  491.         src="/dev/disk/by-label/${src#LABEL=}"
  492.     fi
  493.  
  494.     # Do the preparatory steps
  495.     if ! parse_opts "$opts"; then
  496.         device_msg "$dst" "invalid opts"
  497.         continue
  498.     elif ! check_key; then
  499.         device_msg "$dst" "invalid key"
  500.         continue
  501.     elif ! lo_setup; then
  502.         device_msg "$dst" "loopback failed"
  503.     fi
  504.  
  505.     # Ignore noauto devices
  506.     if [ "$IGNORE" = "yes" ] && [ -z "$FORCE_START" ]; then
  507.         device_msg "$dst" "ignored"
  508.         continue
  509.     fi
  510.  
  511.     # Make sure source device exists
  512.     if [ ! -r "$src" ]; then
  513.         if [ "$LOUD" = "yes" ]; then
  514.             device_msg "$dst" "skipped, device $src does not exist"
  515.         fi
  516.         continue
  517.     fi
  518.  
  519.     # Make sure that target device doesn't exist
  520.     if [ -b "/dev/mapper/$dst" ]; then
  521.         device_msg "$dst" "running"
  522.         continue
  523.     fi
  524.  
  525.     # All checks passed, do the real setup
  526.     log_action_msg "$dst (starting)"
  527.     result="ok"
  528.     if [ "$USELUKS" = "yes" ]; then
  529.         do_luks || result="fail"
  530.     else
  531.         do_noluks || result="fail"
  532.     fi
  533.  
  534.     # Finish up
  535.     if [ "$result" != "ok" ]; then
  536.         rm_lo_setup
  537.         device_msg "$dst" "failed"
  538.     else
  539.         do_swap
  540.         do_tmp
  541.         device_msg "$dst" "started"
  542.     fi
  543.  
  544.     return 0
  545. }
  546.  
  547. handle_crypttab_line_stop () {
  548.     dst=$1
  549.     src=$2
  550.     key=$3
  551.     opts=$4
  552.  
  553.     if [ ! -b "/dev/mapper/$dst" ]; then
  554.         device_msg "$dst" "stopped"
  555.         continue
  556.     fi
  557.  
  558.     opencount=$(dmsetup info -c --noheadings -o open "$dst" 2> /dev/null || true)
  559.     if [ -z "$opencount" ]; then
  560.         device_msg "$dst" "error"
  561.         continue
  562.     elif [ "$opencount" != "0" ]; then
  563.         device_msg "$dst" "busy"
  564.         continue
  565.     fi
  566.  
  567.     #major=$(dmsetup info -c --noheadings -o major "$dst" 2> /dev/null || true)
  568.     #minor=$(dmsetup info -c --noheadings -o minor "$dst" 2> /dev/null || true)
  569.     src_major=$(dmsetup deps "$dst" 2> /dev/null | sed -e 's/^.*(\([0-9]*\), [0-9]*)$/\1/g' || true)
  570.     src_minor=$(dmsetup deps "$dst" 2> /dev/null | sed -e 's/^.*([0-9]*, \([0-9]*\))$/\1/g' || true)
  571.  
  572.     if [ -z "$src_major" ] || [ -z "$src_minor" ]; then
  573.         device_msg "$dst" "error"
  574.         continue
  575.     fi
  576.  
  577.     do_close
  578.  
  579.     # Detach loopback device, if attached
  580.     if [ "$src_major" = "7" ]; then
  581.         loopdev="/dev/loop${src_minor}"
  582.         if ! rm_lo_setup; then
  583.             device_msg "$dst" "detaching loopback failed"
  584.             continue
  585.         fi
  586.     fi
  587.  
  588.     device_msg "$dst" "stopping"
  589.  
  590.     return 0
  591. }
  592.  
  593. do_start () {
  594.     local dst src key opts result
  595.  
  596.     modprobe -qb dm-mod || true
  597.     modprobe -qb dm-crypt || true
  598.     dmsetup mknodes > /dev/null 2>&1 || true
  599.     log_action_begin_msg "Starting $INITSTATE crypto disks"
  600.     mount_fs
  601.  
  602.     egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do
  603.         handle_crypttab_line_start "$dst" "$src" "$key" "$opts" <&3
  604.     done 3<&1
  605.     umount_fs
  606.  
  607.     log_action_end_msg 0
  608. }
  609.  
  610. # Removes all mappings in crypttab
  611. do_stop () {
  612.     local dst src key opts opencount major minor loopmajor
  613.  
  614.     dmsetup mknodes
  615.     log_action_begin_msg "Stopping $INITSTATE crypto disks"
  616.     loopmajor=$(grep "[[:space:]]*loop$" /proc/devices | sed 's/^[[:space:]]*//;s/[[:space:]].*//')
  617.  
  618.     egrep -v "^[[:space:]]*(#|$)" "$TABFILE" | while read dst src key opts; do
  619.         handle_crypttab_line_stop "$dst" "$src" "$key" "$opts" <&3
  620.     done 3<&1
  621.  
  622.     log_action_end_msg 0
  623. }
  624.  
  625. # Convenience function to handle $VERBOSE
  626. device_msg () {
  627.     local dst msg
  628.     dst="$1"
  629.     msg="$2"
  630.  
  631.     if [ "$VERBOSE" != "no" ]; then
  632.         log_action_cont_msg "$dst ($msg)"
  633.     fi
  634. }
  635.